﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data.Common;
using System.Data;
using XMK.Framework.Model;
using XMK.Utils;

namespace XMK.Framework.DataAccess
{
    /// <summary>
    /// 数据库命令
    /// </summary>
    public class DbCmdInfo
    {
        #region 构造方法
        /// <summary>
        /// 私有构造方法，外部无法使用该方法
        /// </summary>
        private DbCmdInfo() { this.Params = new List<IDbDataParameter>(); }
        /// <summary>
        /// 存储过程的命令构造方法
        /// </summary>
        /// <param name="sqlText">存储过程名</param>
        /// <param name="dbParams">参数列表</param>
        public DbCmdInfo(string sqlText, params IDbDataParameter[] dbParams)
            : this(sqlText, CommandType.StoredProcedure, dbParams) { }
        /// <summary>
        /// 命令构造方法
        /// </summary>
        /// <param name="sqlText">Sql语句或存储过程名</param>
        /// <param name="commandType">命令类型</param>
        /// <param name="dbParams">参数列表</param>
        public DbCmdInfo(string sqlText, CommandType commandType, params IDbDataParameter[] dbParams)
            : this()
        {
            this.SqlText = sqlText;
            this.CommandType = commandType;
            if (dbParams != null)
                this.Params.AddRange(dbParams);
        }
        #endregion

        #region 属性
        /// <summary>
        /// Sql命令语句或存储过程
        /// </summary>
        public string SqlText { get; set; }
        /// <summary>
        /// 命令类型
        /// </summary>
        public CommandType CommandType{ get; set; }
        /// <summary>
        /// 参数列表
        /// </summary>
        public List<IDbDataParameter> Params { get; set; }
        /// <summary>
        /// 执行命令并返回受影响的行数
        /// </summary>
        public int ExecuteNonQuery { get; set; }
        #endregion

        #region 获取返回值
        /// <summary>
        /// 返回值的内部保存
        /// </summary>
        private Dictionary<string, object> ReturnOrOutParamValues = null;
        /// <summary>
        /// 取得执行后的语句参数值(参数不区分大小写)
        /// </summary>
        /// <param name="dbProvider">数据库实例</param>
        /// <param name="param">参数名称</param>
        /// <returns>执行后语句后的返回值</returns>
        public object GetReturnOrOutParamValue(DbProvider dbProvider, string param)
        {
            if(ReturnOrOutParamValues == null)
                ReturnOrOutParamValues = GetReturnOrOutParamValues();
            if(ReturnOrOutParamValues.ContainsKey(dbProvider.ParamPrefix+ param))
                return ReturnOrOutParamValues[dbProvider.ParamPrefix+ param];
            return null;
        }
        /// <summary>
        /// 语句执行后Return或Out参数的值列表
        /// </summary>
        /// <returns>包含返回值或输出参数的键值对</returns>
        private Dictionary<string, object> GetReturnOrOutParamValues()
        {
            //生成不区分大小写的字典集合
            Dictionary<string, object> dict = new Dictionary<string, object>(new DictKeyEqual());
            if (this.Params.Count == 0)
                return dict;
            foreach (IDbDataParameter param in this.Params)
            {
                if (param.Direction != ParameterDirection.Input)
                {
                    dict[param.ParameterName] = param.Value;
                }
            }
            return dict;
        }
        /// <summary>
        /// 字典表的主键应该不区分大小写
        /// </summary>
        private class DictKeyEqual : IEqualityComparer<string>
        {
            /// <summary>
            /// 两个主键是否相等
            /// </summary>
            /// <param name="x">主键X</param>
            /// <param name="y">主键Y</param>
            /// <returns>是否不区分大小写的相等</returns>
            public bool Equals(string x, string y)
            {
                return String.Equals(x, y, StringComparison.CurrentCultureIgnoreCase);
            }
            /// <summary>
            /// 主键的HashCode
            /// </summary>
            /// <param name="obj">主键值</param>
            /// <returns>逐渐字符串的HashCode</returns>
            public int GetHashCode(string obj)
            {
                return obj.ToUpper().GetHashCode();
            }
        }
        #endregion

    }
}
